import re
from datetime import datetime
from .common_func.print_logger import PrintLogger


dist_code = {"11": "北京", "12": "天津", "13": "河北", "14": "山西", "15": "内蒙古", "21": "辽宁", "22": "吉林",
             "23": "黑龙江", "31": "上海", "32": "江苏", "33": "浙江", "34": "安徽", "35": "福建", "36": "江西",
             "37": "山东",
             "41": "河南", "42": "湖北", "43": "湖南", "44": "广东", "45": "广西", "46": "海南", "50": "重庆",
             "51": "四川",
             "52": "贵州", "53": "云南", "54": "西藏", "61": "陕西", "62": "甘肃", "63": "青海", "64": "宁夏",
             "65": "新疆",
             "71": "台湾", "81": "香港", "82": "澳门", "91": "国外"}


class UDataLabel:

    # 银⾏卡:算法识别
    @staticmethod
    def check_bank_card(card_num):
        try:
            total = 0
            card_num_length = len(card_num)
            for item in range(1, card_num_length + 1):
                t = int(card_num[card_num_length - item])
                if item % 2 == 0:
                    t *= 2
                    total += t if t < 10 else t % 10 + t // 10
                else:
                    total += t

            if total % 10 == 0:
                return True
            else:
                return False
        except Exception as e:
            PrintLogger.error(e)
            return False

    # ⾝份证:算法
    @staticmethod
    def check_id_number(id_str: str):
        """
        校验字符串是否是合法身份证号
        :param id_str 待校验字符串
        """
        try:
            if len(id_str) != 18 or id_str[:2] not in dist_code.keys():
                return False
            _birth = id_str[6:14]  # 身份证中间8位，对应出生日期

            # 出生日期的合法性检查
            try:
                str_time = _birth[0:4] + "-" + _birth[4:6] + "-" + _birth[6:8] + " 00:00:00"
                datetime.strptime(str_time, '%Y-%m-%d %H:%M:%S')
            except ValueError:
                return False

            _check_res = id_str[17]  # 身份证最后一位
            _w = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
            # 逐位权数
            valid_check_res_list = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
            # 身份证检验位
            _sum = 0
            # 定义累加和
            for i in range(0, 17):
                _sum = _sum + int(id_str[i]) * _w[i]
            # 逐位加权求和
            check_res_index = _sum % 11  # 取余数
            if _check_res != valid_check_res_list[check_res_index]:
                return False
            return True
        except Exception as e:
            PrintLogger.error(e)
            return False

    # 组织机构代码:算法
    @staticmethod
    def check_organization(value):
        try:
            organization_str = value.upper().replace('-', '')
            organization_pattern = r'^[\dA-Z]{8}[X\d]$'
            if re.search(organization_pattern, organization_str, re.S):
                verify_code = [3, 7, 9, 10, 5, 8, 4, 2]
                verify_code = 11 - sum([int((ord(organization_str[index]) - 55)
                                            if organization_str[index].isalpha() else organization_str[index])
                                        * verify_code[index] for index in range(8)]) % 11
                if verify_code == 10:
                    verify_code = 'X'
                elif verify_code == 11:
                    verify_code = '0'
                else:
                    verify_code = str(verify_code)
                if verify_code == organization_str[-1]:
                    return True
                else:
                    return False
            else:
                return False
        except Exception as e:
            PrintLogger.error(e)
            return False

    # 营业执照号码/营业执照注册号:算法
    @staticmethod
    def check_business(value):
        try:
            business_pattern = r'^\d{15}$'
            if re.search(business_pattern, value, re.S):
                verify_code = 10
                for index in range(14):
                    verify_code = (((verify_code % 11 + int(value[index])) % 10 or 10) * 2) % 11
                verify_code = (11 - (verify_code % 10)) % 10
                if str(verify_code) == value[-1]:
                    return True
                else:
                    return False
            else:
                return False
        except Exception as e:
            PrintLogger.error(e)
            return False

    # 统一社会信用代码:算法
    @staticmethod
    def check_credit(value):
        try:
            credit_str = value.upper()
            credit_pattern = r'^(1[129]|5[1239]|9[123]|Y1)\d{6}[\dA-Z]{8}[X\d][\dA-Z]$'
            if len(credit_str) != 18:
                return False
            search = re.search(credit_pattern, credit_str, re.S)
            if search:
                str_to_num = {'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15, 'G': 16, 'H': 17, 'J': 18, 'K': 19,
                              'L': 20, 'M': 21, 'N': 22, 'P': 23, 'Q': 24, 'R': 25, 'T': 26, 'U': 27, 'W': 28, 'X': 29,
                              'Y': 30}
                num_to_str = {10: 'A', 11: 'B', 12: 'C', 13: 'D', 14: 'E', 15: 'F', 16: 'G', 17: 'H', 18: 'J', 19: 'K',
                              20: 'L', 21: 'M', 22: 'N', 23: 'P', 24: 'Q', 25: 'R', 26: 'T', 27: 'U', 28: 'W', 29: 'X',
                              30: 'Y'}
                verify_code = [1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28]
                verify_code = 31 - sum([(str_to_num.get(credit_str[index], 0) if credit_str[index].isalpha() else int(
                    credit_str[index])) * verify_code[index] for index in range(17)]) % 31
                verify_code = num_to_str.get(verify_code, '') if verify_code > 9 else str(verify_code)
                if verify_code == credit_str[-1]:
                    return True
                else:
                    return False
            else:
                return False
        except Exception as e:
            PrintLogger.error(e)
            return False
